import { Logger } from '@nestjs/common';

/**
 * 性能监控装饰器
 * 用于监控方法执行时间和性能指标
 */
export function Performance(methodName?: string) {
  return function (
    target: any,
    propertyName: string,
    descriptor: PropertyDescriptor,
  ) {
    const logger = new Logger(`Performance-${target.constructor.name}`);
    const originalMethod = descriptor.value;
    const displayName =
      methodName || `${target.constructor.name}.${propertyName}`;

    descriptor.value = async function (...args: any[]) {
      const startTime = performance.now();
      const startMemory = process.memoryUsage();

      try {
        const result = await originalMethod.apply(this, args);
        const executionTime = performance.now() - startTime;
        const endMemory = process.memoryUsage();
        const memoryDiff = endMemory.heapUsed - startMemory.heapUsed;

        // 记录性能指标
        logger.debug(
          `${displayName} - 执行时间: ${executionTime.toFixed(2)}ms, 内存变化: ${(memoryDiff / 1024 / 1024).toFixed(2)}MB`,
        );

        // 如果执行时间超过阈值，记录警告
        if (executionTime > 1000) {
          logger.warn(
            `${displayName} - 执行时间过长: ${executionTime.toFixed(2)}ms`,
          );
        }

        return result;
      } catch (error) {
        const executionTime = performance.now() - startTime;
        logger.error(
          `${displayName} - 执行失败，耗时: ${executionTime.toFixed(2)}ms`,
          error,
        );
        throw error;
      }
    };

    return descriptor;
  };
}

/**
 * 高精度性能监控装饰器
 * 适用于需要精确性能监控的关键方法
 */
export function HighPrecisionPerformance(
  options: {
    logLevel?: 'debug' | 'log' | 'warn';
    threshold?: number;
    includeArgs?: boolean;
  } = {},
) {
  const { logLevel = 'debug', threshold = 100, includeArgs = false } = options;

  return function (
    target: any,
    propertyName: string,
    descriptor: PropertyDescriptor,
  ) {
    const logger = new Logger(`HighPerf-${target.constructor.name}`);
    const originalMethod = descriptor.value;
    const methodName = `${target.constructor.name}.${propertyName}`;

    descriptor.value = async function (...args: any[]) {
      const startHrTime = process.hrtime.bigint();
      const startMemory = process.memoryUsage();

      try {
        const result = await originalMethod.apply(this, args);
        const endHrTime = process.hrtime.bigint();
        const executionTimeNs = Number(endHrTime - startHrTime);
        const executionTimeMs = executionTimeNs / 1_000_000;

        const endMemory = process.memoryUsage();
        const memoryStats = {
          heapUsedDiff:
            (endMemory.heapUsed - startMemory.heapUsed) / 1024 / 1024,
          heapTotalDiff:
            (endMemory.heapTotal - startMemory.heapTotal) / 1024 / 1024,
          externalDiff:
            (endMemory.external - startMemory.external) / 1024 / 1024,
        };

        const logMessage = [
          `${methodName} - 执行时间: ${executionTimeMs.toFixed(3)}ms`,
          `内存使用: ${memoryStats.heapUsedDiff.toFixed(2)}MB`,
          includeArgs ? `参数数量: ${args.length}` : '',
        ]
          .filter(Boolean)
          .join(', ');

        if (executionTimeMs > threshold) {
          logger.warn(logMessage);
        } else {
          logger[logLevel](logMessage);
        }

        return result;
      } catch (error) {
        const endHrTime = process.hrtime.bigint();
        const executionTimeMs = Number(endHrTime - startHrTime) / 1_000_000;

        logger.error(
          `${methodName} - 执行失败，耗时: ${executionTimeMs.toFixed(3)}ms`,
          error,
        );
        throw error;
      }
    };

    return descriptor;
  };
}

/**
 * 缓存性能监控装饰器
 * 专门用于监控缓存相关操作的性能
 */
export function CachePerformance(cacheName: string) {
  return function (
    target: any,
    propertyName: string,
    descriptor: PropertyDescriptor,
  ) {
    const logger = new Logger(`Cache-${cacheName}`);
    const originalMethod = descriptor.value;
    const methodName = `${target.constructor.name}.${propertyName}`;

    descriptor.value = async function (...args: any[]) {
      const startTime = performance.now();

      try {
        const result = await originalMethod.apply(this, args);
        const executionTime = performance.now() - startTime;

        // 判断是否为缓存命中（基于执行时间）
        const isCacheHit = executionTime < 10; // 10ms 以下认为是缓存命中

        logger.debug(
          `${methodName} - ${isCacheHit ? '缓存命中' : '缓存未命中'}, 耗时: ${executionTime.toFixed(2)}ms`,
        );

        return result;
      } catch (error) {
        const executionTime = performance.now() - startTime;
        logger.error(
          `${methodName} - 缓存操作失败，耗时: ${executionTime.toFixed(2)}ms`,
          error,
        );
        throw error;
      }
    };

    return descriptor;
  };
}
